<?php
namespace app\common\model;
use think\Db;
/**
 * 短信对象
 */
class Sms{
    /**
     *
     * @param unknown $phone    电话号码
     * @param unknown $content  发送内容
     * @param number $type      发送类型
     * @param string $code      验证码                        例如 : 0
     * @param number $tpl_id    第三方 模板id   例如：1558796
     * @param string $tpl_val   第三方 变量               例如：{"username":"俞天德","time":"2016-10-08 19:47"}
     * @return unknown
     * 0 ：[1640912]注册验证码  => 您的注册验证码是#code#。如非本人操作，请忽略本短信。
     * 1 ：[1640914]修改密码      => 您的修改密码验证码是#code#。如非本人操作，请忽略本短信。
     * 2 ：[1640916]认证短信     => 尊敬的用户[#name#], 恭喜您实名认证成功。如非本人操作，请忽略本短信。
     * 3 ：[1640926]认证失败     => 尊敬的用户[#name#], 您实名认证因[#reason#]认证失败。如非本人操作，请忽略本短信。
     * 4 ：[1655342]审核资料提醒     =>  用户#name#的#info#资料已齐全，请你审核
     */
    public function create($phone, $content, $type=0, $code="", $tpl_id=0, $tpl_val=""){

        //防止短信轰炸
        if($code){
          $rs = Db::name('sms_history')->field("create_time")->where("phone",$phone)->order("id desc")->find();
          $time = time()-60;
          if($rs && $time<$rs['create_time']) return com_error("距离上次发送短信时间不到1分钟！");
        }

        $d = [
            'tpl_id'    => $tpl_id,
            'tpl_val'   => $tpl_val,
            'phone'     => $phone,
            'content'   => $content,
            'type'      => $type,
            'nums'      => ceil( strlen($content)/180 ),
            'code'      => $code,
            'create_time' => time(),
        ];
        $id = Db::name('sms_history')->insertGetId($d);
        #验证码入库
        if( $d['code'] ){
            Db::name('sms_token')->where('phone', $phone)->where('type', $type)->delete();
            $temp = [
                'phone'         => $phone,
                'code'          => $d['code'],
                'type'          => $type,
                'create_time'   => time(),
            ];
            Db::name('sms_token')->insertGetId($temp);
        }
        return $id;
    }

    /**
     * 发送一条短信
     * @param unknown $id  短信表id
     */
    public function sendOne( $id ){
        $rs = Db::name('sms_history')->where('status',0)->where('id',$id)->find();
        if( !$rs )
            return com_error('不存在的短信任务');
            Db::name('sms_history')->update(['id'=>$id, 'status'=>1]);

        #云片网发送短信
        if( $rs['tpl_id'] ){
            $temp = json_decode($rs['tpl_val'],true);
            $tpl_val = "";
            foreach($temp as $k => $v){
                $tpl_val .="&".urlencode("#{$k}#")."=".urlencode($v);
            }
            $tpl_val = ltrim($tpl_val, "&");
            $d = [
                'apikey'    =>  c('a.yunpian_apikey'),
                'mobile'    =>  $rs['phone'],
                'tpl_id'    =>  $rs['tpl_id'],
                'tpl_value' =>  $tpl_val,
            ];
            $url    = "https://sms.yunpian.com/v2/sms/tpl_single_send.json";
        }else{
            $d = [
                'apikey'    =>  c('type.yunpian_apikey'),
                'mobile'    =>  $rs['phone'],
                'text'      =>  $rs['content'],
                'uid'       =>  $id,
                'callback_url' => '',#推送地址推送地址
            ];
            $url    = "https://sms.yunpian.com/v2/sms/single_send.json";
        }
        $result = $this->_yp_single_send($url, $d);
        if( !$result ){
            //if($rs['code']){Db::name('sms_history')->delete($id);}
            Db::name('sms_history')->update(['id'=>$id, 'status'=>3]);
            return com_error('发送失败');
        }

        if( $result['response_data']['code']!=0 ){
            //if($rs['code']){Db::name('sms_history')->delete($id);}
            Db::name('sms_history')->update(['id'=>$id, 'status'=>3]);
            return com_error($result['response_data']['msg']);
        }else{
            Db::name('sms_history')->update(['id'=>$id, 'status'=>2, 'update_time'=>time()]);
        }
        return true;
    }

    /**
     * 云片网发送短信
     * @param unknown $d  短信内容数组
     */
    public function _yp_single_send($url, $d ){
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept:text/plain;charset=utf-8', 'Content-Type:application/x-www-form-urlencoded','charset=utf-8'));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt ($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($d));
        $retry=0;
        do{
            $output = curl_exec($ch);
            $retry++;
        }while((curl_errno($ch) !== 0) && $retry < 1);
        if (curl_errno($ch) !== 0) {
            return com_error('curl错误'.curl_errno($ch));
        }
        $output = trim($output, "\xEF\xBB\xBF");
        $statusCode = curl_getinfo($ch,CURLINFO_HTTP_CODE);
        curl_close($ch);
        return [
            'status'    => $statusCode,
            'post_data' => $d,
            'response_data' => json_decode($output,true),
        ];
    }

    /**
     * 验证短信码
     * @param unknown $phone
     * @param unknown $type
     * @param unknown $code
     */
    public function checkCode($phone, $type, $code){
        $rs = Db::name('sms_token')->where('phone',$phone)->where('type',$type)->find();
        if(!$rs)
            return com_error('验证失败!');

        $time  =  time() - c('a.sms_second');
        if( $rs['create_time']<$time ){
            Db::name('sms_token')->delete( $rs['id'] );
            return com_error('验证码过期');
        }
        if($rs['code']!=$code){
            if($rs['error_times']>9){
              Db::name('sms_token')->delete( $rs['id'] );
            }else{
              Db::name("sms_token")->update(['id'=>$rs['id'],'error_times'=>['exp',"{$rs['error_times']}+1"]]);
            }
            return com_error('验证错误');
        }else{
            Db::name('sms_token')->delete( $rs['id'] );
            return true;
        }
    }
}
